package com.niuwa.p2p.utils.schedule;

import java.util.Calendar;
import java.util.List;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.niuwa.p2p.entity.job.JobEntity;
import com.niuwa.p2p.service.job.JobService;

public class SchedulerHelper {

	private static Logger logger = Logger.getLogger(SchedulerHelper.class);
	private static final String CONFIG_FILE = "quartz-job.properties";
	private static final String IDENTITY_JOB_PREFIX = "job_";
	private static final String IDENTITY_TRIGGER_PREFIX = "trigger_";
	private static final String SCHEDULER_KEY_JOBSERVICE = "myTaskKey";
	@Autowired
	private JobService jobService;// jobService 这个服务是实现管理任务的页面的服务实现
	private Scheduler scheduler;
	
    @Autowired
	private StartJobSchedulerListener startJobSchedulerListener;// 实现自己的Scheduler监听器，程序启动时，任务没创建时就创建


	/**
	 * 启动时，类实例化时就执行
	 */
	public void init() {
		try {

			// 创建一个定时器工厂
			StdSchedulerFactory sf = new StdSchedulerFactory();
			// 初始化quartz-job.properties配置文件
			sf.initialize(Thread.currentThread().getContextClassLoader()
					.getResource(CONFIG_FILE).getFile());
			scheduler = sf.getScheduler();
			// 把jobService放到scheduler上下文，job执行是可以获取并访问。
			scheduler.getContext().put(SCHEDULER_KEY_JOBSERVICE, jobService);
			startJobSchedulerListener.setSchedulerHelper(this);
			// 设置自己的监听器
			scheduler.getListenerManager().addSchedulerListener(
					startJobSchedulerListener);
			// 启动定时器
			scheduler.start();
			logger.info("====================job scheduler start");
		} catch (SchedulerException e) {
			logger.error("error", e);
		}

	}

	/**
	 * 根据jobentity创建并开始任务
	 */
	public boolean createAndStartJob(JobEntity job) {
		JobDetail jobDetail = generateJobDetail(job);
		Trigger trigger = generateTriggerBuilder(job).build();

		try {
			scheduler.scheduleJob(jobDetail, trigger);
			return true;
		} catch (SchedulerException e) {
			logger.error("scheduler.scheduleJob", e);
			return false;
		}
	}

	/**
	 * 清除
	 */
	public void clearAllScheduler() {
		try {
			scheduler.clear();
		} catch (SchedulerException e) {
			logger.error("clearAllScheduler", e);
		}
	}

	/**
	 * 根据jobId和类型删除
	 */
	public boolean removeJob(Long jobId, String jobGroup) {
		try {
			scheduler.deleteJob(getJobKey(jobId, jobGroup));
			return true;
		} catch (SchedulerException e) {
			logger.error("removeJob", e);
			return false;
		}
	}

	/**
	 * 暂停任务
	 */
	public boolean pauseJob(Long jobId, String jobGroup) {
		try {
			scheduler.pauseJob(getJobKey(jobId, jobGroup));
			return true;
		} catch (SchedulerException e) {
			logger.error("resumeJob", e);
			return false;
		}
	}

	/**
	 * 马上只执行一次任务
	 */
	public boolean executeOneceJob(Long jobId, String jobGroup) {
		try {
			Calendar end = Calendar.getInstance();
			TriggerBuilder<SimpleTrigger> simpleTriggerBuilder = TriggerBuilder
					.newTrigger()
					.withIdentity(getTriggerKey(jobId, jobGroup))
					.forJob(getJobKey(jobId, jobGroup))
					.withSchedule(
							SimpleScheduleBuilder.simpleSchedule()
									.withIntervalInSeconds(2));
			end.add(Calendar.SECOND, 2);
			simpleTriggerBuilder.startAt(end.getTime());
			end.add(Calendar.SECOND, 5);
			simpleTriggerBuilder.endAt(end.getTime());
			JobEntity job = jobService.getJobById(jobId);

			JobDataMap jobDataMap = new JobDataMap();
			jobDataMap.put("jobEntity", job);
			simpleTriggerBuilder.usingJobData(jobDataMap);
			Trigger trigger = simpleTriggerBuilder.build();

			scheduler.scheduleJob(trigger);
			return true;
		} catch (SchedulerException e) {
			logger.error("executeOneceJob", e);
			return false;
		}
	}

	/**
	 * 恢复任务
	 */
	public boolean resumeJob(Long jobId, String jobGroup)
			throws SchedulerException {
		try {
			scheduler.resumeJob(getJobKey(jobId, jobGroup));
			return true;
		} catch (SchedulerException e) {
			logger.error("resumeJob", e);
			return false;
		}
	}

	/**
	 * 启动一些scheduler里没有的active的jobDetail
	 */
	public void createActiveJobFromDB() throws SchedulerException {
		List<JobEntity> jobs = jobService.getActiveJob();
		if (null == jobs) {
			return;
		}
		for (JobEntity job : jobs) {
			if (scheduler.getJobDetail(getJobKey(job)) == null)
				createAndStartJob(job);
		}
	}

	/**
	 * 获得任务的jobKey
	 */
	public static JobKey getJobKey(Long jobId, String jobGroup) {
		return new JobKey(IDENTITY_JOB_PREFIX + jobId, IDENTITY_JOB_PREFIX
				+ jobGroup); // jobType 保留字段
	}

	/**
	 * 获得任务的jobKey
	 */

	public static JobKey getJobKey(JobEntity job) {
		return new JobKey(IDENTITY_JOB_PREFIX + job.getJobId(),
				IDENTITY_JOB_PREFIX + job.getJobGroup()); // job.getJobType()保留字段
	}

	/**
	 * 获得trigger的key
	 */
	public static TriggerKey getTriggerKey(JobEntity job) {
		return new TriggerKey(IDENTITY_TRIGGER_PREFIX + job.getJobId() + "_"
				+ System.currentTimeMillis(), IDENTITY_TRIGGER_PREFIX
				+ job.getJobGroup()); // job.getJobType()保留字段
	}

	/**
	 * 获得trigger的key
	 */
	public static TriggerKey getTriggerKey(Long jobId, String jobGroup) {
		return new TriggerKey(IDENTITY_TRIGGER_PREFIX + jobId + "_"
				+ System.currentTimeMillis(), IDENTITY_TRIGGER_PREFIX
				+ jobGroup);
	}

	public static JobDetail generateJobDetail(JobEntity job) {
		JobDataMap jobDataMap = new JobDataMap();
		jobDataMap.put("jobEntity", job);
		Class<? extends Job> clazz = null;
		clazz = BeanJob.class;
		return JobBuilder.newJob(clazz).withIdentity(getJobKey(job))
				.usingJobData(jobDataMap).requestRecovery(true)
				.storeDurably(true).build();
	}

	/**
	 * 根据jobEntity获得trigger
	 */

	public static TriggerBuilder<CronTrigger> generateTriggerBuilder(
			JobEntity job) {
		TriggerBuilder<CronTrigger> triggerBuilder = TriggerBuilder
				.newTrigger()
				.withIdentity(getTriggerKey(job))
				.withSchedule(
						CronScheduleBuilder.cronSchedule(
								job.getCronExpression())
								.withMisfireHandlingInstructionDoNothing());
		if (job.getSyncBeginTime() != null)
			triggerBuilder.startAt(job.getSyncBeginTime());
		else
			triggerBuilder.startNow();

		if (job.getSyncEndTime() != null)
			triggerBuilder.endAt(job.getSyncEndTime());

		return triggerBuilder;
	}

	public static JobService getJobService(JobExecutionContext context) {
		try {
			return (JobService) context.getScheduler().getContext()
					.get(SchedulerHelper.SCHEDULER_KEY_JOBSERVICE);
		} catch (SchedulerException e) {
			logger.error("SchedulerHelper.getJobService", e);
			return null;
		}
	}

	/**
	 * 页面执行操作封装初始化方法
	 */

	public void getScheduler() {
		try {
			// 创建一个定时器工厂
			StdSchedulerFactory sf = new StdSchedulerFactory();
			// 初始化quartz-job.properties配置文件
			sf.initialize(Thread.currentThread().getContextClassLoader()
					.getResource(CONFIG_FILE).getFile());
			scheduler = sf.getScheduler();
		} catch (SchedulerException e) {
			logger.error("error", e);
		}
	}
}
